﻿// <copyright file="IndexesEnumeratorTests.cs" company="Sinbadsoft">
//        Copyright (c) Sinbadsoft 2009.
//        This file is released under the terms of the
//        GNU Library General Public License (LGPL) version 2.1
//        Please refer to the "License.txt" accompanying this file.
// </copyright>
// <author>Chaker NAKHLI</author>
// <email>Chaker.Nakhli@Sinbadsoft.com</email>
// <date>2009/03/01</date>

namespace Sinbadsoft.AdvancedCollections.Tests.DynamicArray
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;

    using MbUnit.Framework;

    /// <summary>
    /// Tests the <see cref="IndexesEnumerator"/> class.
    /// </summary>
    [TestFixture]
    public static class IndexesEnumeratorTests
    {
        [StaticTestFactory]
        public static IEnumerable<Test> BuildTests()
        {
            IList<Test> tests = new List<Test>();
            IterationData[] data = new IterationData[]
                                       {
                                               new IterationData(new int[] { 0 }, new int[] { 125 }),
                                               new IterationData(new int[] { 10258 }, new int[] { 11169 }),
                                               new IterationData(new int[] { 0, 0 }, new int[] { 150, 17 }),
                                               new IterationData(new int[] { 100, 1560 }, new int[] { 320, 1587 }),
                                               new IterationData(new int[] { 0, 0, 0 }, new int[] { 49, 17, 9 }),
                                               new IterationData(new int[] { 12000, 15000, 158220 }, new int[] { 12010, 15015, 158270 }),
                                               new IterationData(new int[] { 0, 0, 0, 0 }, new int[] { 10, 7, 12, 18 }),
                                               new IterationData(new int[] { 30, 300, 3000, 30000 }, new int[] { 35, 317, 3002, 30018 })
                                       };

            foreach (IterationData itdata in data)
            {
                string prefix = string.Format(CultureInfo.InvariantCulture, "Rank ({0}) Range ", itdata.Start.Length);
                IterationData itdatacopy = itdata;
                tests.Add(new TestCase(prefix + itdatacopy, delegate { TestRange(itdatacopy); }));
                tests.Add(new TestCase(prefix + ToReverse(itdatacopy), delegate { TestRange(ToReverse(itdatacopy)); }));
            }

            return tests; 
        }

        private static void TestRange(IterationData itdata)
        {
            IndexesEnumerator ienum = new IndexesEnumerator(itdata.End, itdata.Start, itdata.Reverse);

            RecursiveArrayEnumerator.Iterate(
                null,
                itdata.Start,
                itdata.End,
                new IndexesEnumeratorTestAction(ienum).Iterate,
                itdata.Reverse);
        }

        private static IterationData ToReverse(IterationData itdata)
        {
            return new IterationData(
                IndexesHelper.Add(itdata.End, -1),
                IndexesHelper.Add(itdata.Start, -1),
                !itdata.Reverse);
        }

        private struct IterationData
        {
            public readonly int[] Start;
            public readonly int[] End;
            public readonly bool Reverse;

            public IterationData(int[] start, int[] end) : this(start, end, false)
            {
            }

            public IterationData(int[] start, int[] end, bool reverse)
            {
                this.Start = start;
                this.End = end;
                this.Reverse = reverse;
            }

            public override string ToString()
            {
                return "R: " + this.Reverse + " S: " + ArrayHelper.SequenceToString(this.Start) + 
                    " E: " + ArrayHelper.SequenceToString(this.End);
            }
        }
        
        private class IndexesEnumeratorTestAction
        {
            private readonly IndexesEnumerator ienum;

            public IndexesEnumeratorTestAction(IndexesEnumerator ienum)
            {
                this.ienum = ienum;
            }

            public void Iterate(Array arr, params int[] indexes)
            {
                Assert.IsTrue(this.ienum.MoveNext());
                Assert.AreElementsEqual(indexes, this.ienum.Current);
            }
        }
    }
}